﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Security.Cryptography;

namespace MobileAPI.Common
{
    /// <summary>
    /// 加密工具
    /// </summary>
    public static class MobileCryptoUtil
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="input">明文</param>
        /// <param name="key">密钥</param>
        /// <returns>十六进制编码的密文</returns>
        public static string Encrypt(string input, string key)
        {
            if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("明文和密钥均不能为空。");
            }

            // 明文和密钥
            byte[] p = Encoding.UTF8.GetBytes(input);
            byte[] k = Encoding.UTF8.GetBytes(key);

            // 将明文长度扩大一倍，将一个字节 8 位分成两部分进行存储
            byte[] w = new byte[p.Length * 2];
            for (int i = 0; i < p.Length; i++)
            {
                w[i] = (byte)((p[i] & 0xF0) >> 4);
                w[w.Length - i - 1] = (byte)(p[i] & 0x0F);
            }

            // 若长度大于 128 则重新合并，恢复明文长度
            byte[] t = null;
            if (w.Length > 128)
            {
                t = new byte[w.Length / 2 + 1];
                t[0] = 0;
                for (int i = 0; i < w.Length - 1; i += 2)
                {
                    t[i / 2 + 1] = (byte)((w[i] << 4) + w[i + 1]);
                }
            }
            else
            {
                t = new byte[w.Length + 1];
                t[0] = 1;
                for (int i = 0; i < w.Length; i++)
                {
                    t[i + 1] = w[i];
                }
            }

            // 密文
            byte[] r = new byte[t.Length];

            // 明文取反然后与密钥按位异或
            for (int i = 0; i < t.Length; i++)
            {
                int j = i % k.Length;
                r[i] = (byte)((~t[i]) ^ k[j]);
            }

            return ToHexString(r);
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="input">十六进制编码的密文</param>
        /// <param name="key">密钥</param>
        /// <returns>明文</returns>
        public static string Decrypt(string input, string key)
        {
            if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("密文和密钥均不能为空。");
            }

            // 密文和密钥
            byte[] c = FromHexString(input);
            byte[] k = Encoding.UTF8.GetBytes(key);

            // 密文与密钥按位异或然后取反
            byte[] p = new byte[c.Length];
            for (int i = 0; i < c.Length; i++)
            {
                int j = i % k.Length;
                p[i] = (byte)(~((c[i]) ^ k[j]));
            }

            // 明文长度没有被扩大一倍
            byte[] t = null;
            if (p[0] == 0)
            {
                t = new byte[(p.Length - 1) * 2];
                for (int i = 1; i < p.Length; i++)
                {
                    t[(i - 1) * 2] = (byte)((p[i] & 0xF0) >> 4);
                    t[i * 2 - 1] = (byte)(p[i] & 0x0F);
                }
            }
            else
            {
                t = new byte[p.Length - 1];
                for (int i = 1; i < p.Length; i++)
                {
                    t[i - 1] = p[i];
                }
            }

            // 获取原始明文
            byte[] w = new byte[t.Length / 2];
            for (int i = 0; i < w.Length; i++)
            {
                w[i] = (byte)((t[i] << 4) + t[t.Length - i - 1]);
            }

            return Encoding.UTF8.GetString(w);
        }

        /// <summary>
        /// 将 byte 数组转换成 16 进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static String ToHexString(byte[] bytes)
        {
            return BitConverter.ToString(bytes).Replace("-", "");
        }

        /// <summary>
        /// 将 16 进制字符串转换为 byte 数组
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static byte[] FromHexString(string s)
        {
            if (s == null || s.Length <= 0)
            {
                throw new ArgumentNullException(" 16 进制字符串不能为空。");
            }

            byte[] result = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                result[i / 2] = byte.Parse(s.Substring(i, 2), NumberStyles.HexNumber);
            }
            return result;
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="strPwd"></param>
        /// <returns></returns>
        public static string MD5(string strPwd)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                byte[] inputdata = System.Text.Encoding.UTF8.GetBytes(strPwd);
                //将字符编码为一个字节序列 
                byte[] outputdata = md5.ComputeHash(inputdata);
                //计算data字节数组的哈希值 
                md5.Clear();
                string str = "";
                for (int i = 0; i < outputdata.Length - 1; i++)
                    str += System.Convert.ToString(outputdata[i], 16);
                return str;
            }
        }
    
    }
}
